package com.loveprogrammer.engine.battle;

import com.loveprogrammer.dto.battle.BattleFightResult;
import com.loveprogrammer.engine.AttackResult;
import com.loveprogrammer.factory.JobFactory;
import com.loveprogrammer.factory.MonsterFactory;
import com.loveprogrammer.model.Character;
import com.loveprogrammer.model.Coin;
import com.loveprogrammer.model.Hero;
import com.loveprogrammer.model.Monster;
import com.loveprogrammer.model.game.HeroWrapper;
import com.loveprogrammer.model.goods.Equipment;
import com.loveprogrammer.model.goods.Goods;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.*;

/**
 * @ClassName BattleEngine
 * @Description 多对多战斗引擎 - PVE
 * @Author admin
 * @Date 2024/2/20 17:03
 * @Version 1.0
 */
public class BattleEngine {

    // 队列不变
    private final LinkedList<Attack> actions = new LinkedList<>();

    private List<Goods> fallingGoods = new ArrayList<>();

    private final HeroWrapper heroWrapper;

    private Coin fallingCoin = new Coin();

    private int fallingExp = 0;

    private int max_monster_level = 0;

    private FallingGoods fallingGoodsCalculator = new FallingGoodsCalculator();
    private FallingCoin fallCoinCalculator = FallingCoinCalculator.getInstance();

    public BattleEngine(HeroWrapper heroWrapper) {
        this.heroWrapper = heroWrapper;
    }

    private int addAction(Attack action) {
        actions.offer(action);
        return actions.size();
    }

    public BattleFightResult fight(List<? extends Character> listA, List<? extends Character> listB) throws InterruptedException {
        BattleFightResult result = new BattleFightResult();
        List<String> fightLogs = result.getFightLogs();
        // 先初始化
        listA.sort(Comparator.comparing(Character::getSpeed).reversed());
        for (int i = 0; i < listA.size(); i++) {
            addAction(new GroupAttack(listA.get(i), listB));
        }

        // 再放入listB
        listB.sort(Comparator.comparing(Character::getSpeed).reversed());
        for (int i = 0; i < listB.size(); i++) {
            GroupAttack attack = new GroupAttack(listB.get(i), listA);
            insertAction(attack);
        }

        // 如果A集合和B集合的生命值都还大于0

        while (listA.stream().anyMatch(e -> e.getCurrentHp() > 0) && listB.stream().anyMatch(e -> e.getCurrentHp() > 0)) {
            Attack pop = actions.pop();
            AttackResult run = pop.run();
            if (run != null && run.getSuccess()) {
                fightLogs.addAll(run.getContent());
                // 检查是否有被消灭的野怪
                if (!CollectionUtils.isEmpty(run.getDeadCharacters())) {
                    for (Character deadCharacter : run.getDeadCharacters()) {
                        if (listB.contains(deadCharacter)) {
                            deadEvent(deadCharacter);
                        }
                    }

                }
                // 再放进去
                if (pop.checkContinue()) {
                    // 要重新计算interval的时间
                    pop.setIntervalTime(pop.getIntervalTime() + pop.computeInterval(pop.speed()));
                    insertAction(pop);
                }
            }

        }

        if (listA.stream().anyMatch(e -> e.getCurrentHp() > 0)) {
            result.setWin(true);
            if (fallingExp > 0) {
                result.addConsole("获得经验" + fallingExp + "点");
                // 获取经验经验
                getHeroWrapper().addExp(fallingExp, max_monster_level,result);
            }
            if (fallingCoin.getGoldCoin() > 0) {
                result.addConsole("获得金币" + fallingCoin.getGoldCoin());
                getHeroWrapper().getWarehouse().pickUp(fallingCoin);
            }
            if (fallingGoods.size() > 0) {
                for (Goods fallingGood : fallingGoods) {
                    result.addConsole("获得物品" + fallingGood.toString());
                }
                getHeroWrapper().getWarehouse().pickUp(fallingGoods);
            }
        } else {
            result.setWin(false);
        }
        return result;
    }

    // 死亡之后的调整
    private void deadEvent(Character deadCharacter) {
        if (deadCharacter instanceof Monster) {
            Monster monster = (Monster) deadCharacter;
            // 物品的掉落
            fallingGoods.addAll(fallingGoodsCalculator.setMonster(monster).getFallingProduct());
            // 金币的掉落
            fallingCoin.add(fallCoinCalculator.getFallingCoin(monster));
            // 经验值掉落
            fallingExp += monster.getDeadExp();
        }
    }

    private void insertAction(Attack attack) {
        int intervalTime = attack.getIntervalTime();

        // 如果第一个就大于attack的interval
        if (actions.get(0).getIntervalTime() > attack.intervalTime()) {
            // 在头插入一个
            actions.push(attack);
        } else {
            ListIterator<Attack> iterator = actions.listIterator();
            while (iterator.hasNext()) {
                Attack next = iterator.next();

                if (next.getIntervalTime() > intervalTime) {
                    break;
                }
            }
            // 在指定位置插入新元素
            iterator.add(attack);
        }
    }

    public HeroWrapper getHeroWrapper() {
        return heroWrapper;
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {

        Hero heroA = JobFactory.createHero(JobFactory.getTemplates().get(0), "haha");
        Monster monster = MonsterFactory.createMonster(101, 1);

        HeroWrapper wrapper = new HeroWrapper(heroA);
        BattleEngine engine = new BattleEngine(wrapper);
        BattleFightResult fight = engine.fight(Arrays.asList(heroA), Arrays.asList(monster));

        for (String fightLog : fight.getFightLogs()) {
            System.out.println(fightLog);
        }

        System.out.println("当前英雄经验" + heroA.getCurrentExp());
        System.out.println("当前英雄金币" + wrapper.getWarehouse().getGoldCoin());
        System.out.println("当前英雄装备");

        for (Equipment equipment : wrapper.getWarehouse().getEquipmentList()) {
            System.out.println(equipment.prettyPrint());
        }
    }


}
